<?php

namespace App\Admin\Controllers;

use App\Models\Order;
use App\Http\Controllers\Controller;
use Encore\Admin\Controllers\HasResourceActions;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Encore\Admin\Show;
use Encore\Admin\Facades\Admin;
use Illuminate\Http\Request;
use App\Exceptions\InvalidRequestException;
use App\Http\Requests\Admin\HandleRefundRequest;
use App\Exceptions\InternalException;

class OrdersController extends Controller
{
    use HasResourceActions;

    /**
     * Index interface.
     *
     * @param Content $content
     * @return Content
     */
    public function index(Content $content)
    {
        return $content
            ->header('订单列表')
            ->body($this->grid());
    }

    /**
     * Edit interface.
     *
     * @param mixed   $id
     * @param Content $content
     * @return Content
     */

    public function show(Order $order)
    {
        return Admin::content(function (Content $content) use ($order) {
            $content->header('查看订单');
            // body 方法可以接受 Laravel 的视图作为参数
            $content->body(view('admin.orders.show', ['order' => $order]));
        });
    }


    /**
     * Make a grid builder.
     *
     * @return Grid
     */
    protected function grid()
    {
        $grid = new Grid(new Order);

//        $grid->model()->whereNotNull('paid_at')->orderBy('paid_at','desc');
        $grid->model()->orderBy('paid_at','desc');
        $grid->no('订单流水号');
        $grid->column('user.name','买家');
        $grid->total_amount('总金额');
        $grid->paid_at('支付时间')->sortable();
        $grid->ship_status('物流')->display(
          function ($value){
              return Order::$shipStatusMap[$value];
          }
        );
        $grid->refund_status('退款状态')->display(function($value) {
            return Order::$refundStatusMap[$value];
        });

        // 禁用创建按钮，后台不需要创建订单
        $grid->disableCreateButton();
        $grid->actions(function ($actions) {
            // 禁用删除和编辑按钮
            $actions->disableDelete();
//            $actions->disableEdit();
        });
        $grid->tools(function ($tools) {
            // 禁用批量删除按钮
            $tools->batch(function ($batch) {
                $batch->disableDelete();
            });
        });

        return $grid;
    }

    /**
     * Make a show builder.
     *
     * @param mixed   $id
     * @return Show
     */
    protected function detail($id)
    {
        $show = new Show(Order::findOrFail($id));

        $show->id('Id');
        $show->no('No');
        $show->user_id('User id');
        $show->address('Address');
        $show->total_amount('Total amount');
        $show->remark('Remark');
        $show->paid_at('Paid at');
        $show->payment_method('Payment method');
        $show->payment_no('Payment no');
        $show->refund_status('Refund status');
        $show->refund_no('Refund no');
        $show->closed('Closed');
        $show->reviewed('Reviewed');
        $show->ship_status('Ship status');
        $show->ship_data('Ship data');
        $show->extra('Extra');
        $show->created_at('Created at');
        $show->updated_at('Updated at');

        return $show;
    }

    public function edit($id,Content $content)
    {
        return $content
            ->header('编辑订单')
            ->body($this->form()->edit($id));
    }

    /**
     * Make a form builder.
     *
     * @return Form
     */

    protected function form()
    {
        $form = new Form(new Order);
        $form->display('no','订单流水号');
        $form->display('user.name','买家');
        $form->display('paid_at','支付时间');
        $form->display('payment_method','支付方式');
        //json数据处理
        $form->embeds('address', '', function ($form) {
            $form->text('address','详细地址');
            $form->text('zip','邮编');
            $form->mobile('contact_phone','电话');
        });
        $form->currency('total_amount','金额')->symbol('￥');
        $form->text('remark','订单备注');

        $form->tools(function (Form\Tools $tools) {
            //禁用按钮
            $tools->disableDelete();
//            $tools->disableView();
//            $tools->disableList();
        });
        return $form;
    }

    /**
     * 发货接口
     */
    public function ship(Order $order,Request $request)
    {
        //判断当前是否已经支付
        if (!$order->paid_at){
            throw new InvalidRequestException('该订单已发货');
        }

        //判断订单状态是否已经发货
        if ($order->ship_status !== Order::SHIP_STATUS_PENDING){
            throw new InvalidRequestException('该订单已发货');
        }
        // Laravel 5.5 之后 validate 方法可以返回校验过的值
        $data = $this->validate($request, [
            'express_company' => ['required'],
            'express_no'      => ['required'],
        ], [], [
            'express_company' => '物流公司',
            'express_no'      => '物流单号',
        ]);
        // 将订单发货状态改为已发货，并存入物流信息
        $order->update([
            'ship_status' => Order::SHIP_STATUS_DELIVERED,
            // 我们在 Order 模型的 $casts 属性里指明了 ship_data 是一个数组
            // 因此这里可以直接把数组传过去
            'ship_data'   => $data,
        ]);

        // 返回上一页
        return redirect()->back();
    }

    //拒绝退款
    public function handleRefund(Order $order, HandleRefundRequest $request)
    {
        // 判断订单状态是否正确
        if ($order->refund_status !== Order::REFUND_STATUS_APPLIED) {
            throw new InvalidRequestException('订单状态不正确');
        }
        // 是否同意退款
        if ($request->input('agree')) {
            // 退款逻辑
            $this->_refundOrder($order);
        } else {
            // 将拒绝退款理由放到订单的 extra 字段中
            $extra = $order->extra ?: [];
            $extra['refund_disagree_reason'] = $request->input('reason');
            // 将订单的退款状态改为未退款
            $order->update([
                'refund_status' => Order::REFUND_STATUS_PENDING,
                'extra'         => $extra,
            ]);
        }

        return $order;
    }

    public function _refundOrder(Order $order)
    {
        //判断该订单的支付方式
        switch ($order->payment_method){
            case 'wechat':
                //微信支付
                //生成退款订单号
                $refundNo = Order::getAvailableRefundNo();
                app('wechat_pay')->refund([
                    'out_trade_no' => $order->no, // 之前的订单流水号
                    'total_fee' => $order->total_amount * 100, //原订单金额，单位分
                    'refund_fee' => $order->total_amount * 100, // 要退款的订单金额，单位分
                    'out_refund_no' => $refundNo, // 退款订单号
                    // 微信支付的退款结果并不是实时返回的，而是通过退款回调来通知，因此这里需要配上退款回调接口地址
                    'notify_url' => 'payment.wechat.refund_notify' // 开发环境的话，需要配成 requestbin 地址
                ]);
                // 将订单状态改成退款中
                $order->update([
                    'refund_no' => $refundNo,
                    'refund_status' => Order::REFUND_STATUS_PROCESSING,
                ]);

            break;
            case 'alipay':
                //生成退款订单号
                $refundNo = Order::getAvailableRefundNo();
                //调用支付宝实例的refund方法
            $ret = app('alipay')->refund([
                'out_trade_no' => $order->no, // 之前的订单流水号
                'refund_amount' => $order->total_amount, // 退款金额，单位元
                'out_request_no' => $refundNo, // 退款订单号
            ]);
            // 根据支付宝的文档，如果返回值里有 sub_code 字段说明退款失败
            if ($ret->sub_code){
                //将退看信息信息保存在extra字段
                $extra = $order->extra;
                $extra['refund_failed_code'] = $ret->sub_code;
                //将订单标记为退看失败
                $order->update([
                    'refund_no' => $refundNo,
                    'refund_status' => Order::REFUND_STATUS_FAILED,
                    'extra' => $extra,
                ]);
            }else {
                // 将订单的退款状态标记为退款成功并保存退款订单号
                $order->update([
                    'refund_no' => $refundNo,
                    'refund_status' => Order::REFUND_STATUS_SUCCESS,
                ]);
            }
            break;
            default://原则上不可能出现以防万一
                throw new InternalException('未知支付方式：'. $order->payment_method);
            break;
        }
    }

}
